﻿using System.Reflection;
using System.Runtime.InteropServices;
using OnDash.Windowing.GraphicsLibraryFramework.Enums;
using OnDash.Windowing.GraphicsLibraryFramework.Inputs;
using static OnDash.Windowing.GraphicsLibraryFramework.GlfwCallbacks;

namespace OnDash.Windowing.GraphicsLibraryFramework;

public unsafe struct GlfwNative
{
    private const string Library = "glfw3.dll";

    public const int GlfwTrue = 1;
    public const int GlfwFalse = 0;

    static GlfwNative()
    {
        NativeLibrary.SetDllImportResolver(typeof(GlfwNative).Assembly,
            (name, assembly, path) => name != Library
                ? IntPtr.Zero
                : LoadLibrary("glfw", new Version(3, 3), assembly, path));
    }

    private static IntPtr LoadLibrary(string libraryName, Version version, Assembly assembly,
        DllImportSearchPath? searchPath)
    {
        IEnumerable<string> GetNextVersion()
        {
            for (var i = 2; i >= 0; i--) yield return version.ToString(i);
        }

        Func<string, string, string> libNameFormatter;
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            libNameFormatter = (libName, ver) =>
                libName + ".so" + (string.IsNullOrEmpty(ver) ? string.Empty : "." + ver);
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            libNameFormatter = (libName, ver) =>
                libName + (string.IsNullOrEmpty(ver) ? string.Empty : "." + ver) + ".dylib";
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            libNameFormatter = (libName, ver) =>
                libName + (string.IsNullOrEmpty(ver) ? string.Empty : ver) + ".dll";
        else return IntPtr.Zero;

        foreach (var ver in GetNextVersion())
            if (NativeLibrary.TryLoad(libNameFormatter(libraryName, ver), assembly, searchPath, out var handle))
                return handle;

        return NativeLibrary.Load(libraryName, assembly, searchPath);
    }

    [DllImport(Library, EntryPoint = "glfwInit", CallingConvention = CallingConvention.Cdecl)]
    public static extern int Init();

    [DllImport(Library, EntryPoint = "glfwTerminate", CallingConvention = CallingConvention.Cdecl)]
    public static extern void Terminate();

    [DllImport(Library, EntryPoint = "glfwInitHint", CallingConvention = CallingConvention.Cdecl)]
    public static extern void InitHint(int hint, int value);

    [DllImport(Library, EntryPoint = "glfwGetVersion", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetVersion(int* major, int* minor, int* revision);

    [DllImport(Library, EntryPoint = "glfwGetVersionString", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetVersionString();

    [DllImport(Library, EntryPoint = "glfwGetError", CallingConvention = CallingConvention.Cdecl)]
    public static extern ErrorCode GetError(byte** description);

    [DllImport(Library, EntryPoint = "glfwGetMonitor", CallingConvention = CallingConvention.Cdecl)]
    public static extern Monitor** GetMonitors(int* count);

    [DllImport(Library, EntryPoint = "glfwGetMonitorPos", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetMonitorPos(Monitor* monitor, int* x, int* y);

    [DllImport(Library, EntryPoint = "glfwGetMonitorWorkarea", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetMonitorWorkarea(Monitor* monitor, int* posX, int* posY, int* width, int* height);

    [DllImport(Library, EntryPoint = "glfwGetMonitorPhysicalSize", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetMonitorPhysicalSize(Monitor* monitor, int* width, int* height);

    [DllImport(Library, EntryPoint = "glfwGetMonitorContentScale", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetMonitorContentScale(Monitor* monitor, float* scaleX, float* scaleY);

    [DllImport(Library, EntryPoint = "glfwGetMonitorName", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetMonitorName(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwSetMonitorUserPointer", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetMonitorUserPointer(Monitor* monitor, void* pointer);

    [DllImport(Library, EntryPoint = "glfwGetMonitorUserPointer", CallingConvention = CallingConvention.Cdecl)]
    public static extern void* GetMonitorUserPointer(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwGetVideoModes", CallingConvention = CallingConvention.Cdecl)]
    public static extern VideoMode* GetVideoModes(Monitor* monitor, int* count);

    [DllImport(Library, EntryPoint = "glfwSetGamma", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetGamma(Monitor* monitor, float gamma);

    [DllImport(Library, EntryPoint = "glfwGetGammaRamp", CallingConvention = CallingConvention.Cdecl)]
    public static extern GammaRamp* GetGammaRamp(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwSetGammaRamp", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetGammaRamp(Monitor* monitor, GammaRamp* ramp);

    [DllImport(Library, EntryPoint = "glfwDefaultWindowHints", CallingConvention = CallingConvention.Cdecl)]
    public static extern void DefaultWindowHints();

    [DllImport(Library, EntryPoint = "glfwWindowHintString", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WindowHintString(int hint, byte* value);

    [DllImport(Library, EntryPoint = "glfwSetWindowSizeLimits", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowSizeLimits(Window* window, int minWidth, int minHeight, int maxWidth,
        int maxHeight);

    [DllImport(Library, EntryPoint = "glfwSetWindowAspectRatio", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowAspectRatio(Window* window, int numer, int denom);

    [DllImport(Library, EntryPoint = "glfwGetWindowFrameSize", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetWindowFrameSize(Window* window, int* left, int* top, int* right, int* bottom);

    [DllImport(Library, EntryPoint = "glfwGetWindowContentScale", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetWindowContentScale(Window* window, float* scaleX, float* scaleY);

    [DllImport(Library, EntryPoint = "glfwGetWindowOpacity", CallingConvention = CallingConvention.Cdecl)]
    public static extern float GetWindowOpacity(Window* window);

    [DllImport(Library, EntryPoint = "glfwSetWindowOpacity", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowOpacity(Window* window, float opacity);

    [DllImport(Library, EntryPoint = "glfwRequestWindowAttention", CallingConvention = CallingConvention.Cdecl)]
    public static extern void RequestWindowAttention(Window* window);

    [DllImport(Library, EntryPoint = "glfwSetWindowAttrib", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowAttrib(Window* window, WindowAttribute attrib, int value);

    [DllImport(Library, EntryPoint = "glfwRawMouseMotionSupported", CallingConvention = CallingConvention.Cdecl)]
    public static extern int RawMouseMotionSupported();

    [DllImport(Library, EntryPoint = "glfwGetKeyName", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetKeyName(Keys key, int scancode);

    [DllImport(Library, EntryPoint = "glfwGetKeyScancode", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetKeyScancode(Keys key);

    [DllImport(Library, EntryPoint = "glfwGetKey", CallingConvention = CallingConvention.Cdecl)]
    public static extern InputAction GetKey(Window* window, Keys key);

    [DllImport(Library, EntryPoint = "glfwGetMouseButton", CallingConvention = CallingConvention.Cdecl)]
    public static extern InputAction GetMouseButton(Window* window, MouseButton button);

    [DllImport(Library, EntryPoint = "glfwGetCursorPos", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetCursorPos(Window* window, float* posX, float* posY);

    [DllImport(Library, EntryPoint = "glfwSetCursorPos", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetCursorPos(Window* window, float posX, float posY);

    [DllImport(Library, EntryPoint = "glfwCreateCursor", CallingConvention = CallingConvention.Cdecl)]
    public static extern Cursor* CreateCursor(Image* image, int hotX, int hotY);

    [DllImport(Library, EntryPoint = "glfwCreateStandardCursor", CallingConvention = CallingConvention.Cdecl)]
    public static extern Cursor* CreateStandardCursor(CursorShape shape);

    [DllImport(Library, EntryPoint = "glfwDestroyCursor", CallingConvention = CallingConvention.Cdecl)]
    public static extern void DestroyCursor(Cursor* cursor);

    [DllImport(Library, EntryPoint = "glfwSetCursor", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetCursor(Window* window, Cursor* cursor);

    [DllImport(Library, EntryPoint = "glfwJoystickPresent", CallingConvention = CallingConvention.Cdecl)]
    public static extern int JoystickPresent(int jId);

    [DllImport(Library, EntryPoint = "glfwGetJoystickAxes", CallingConvention = CallingConvention.Cdecl)]
    public static extern float* GetJoystickAxes(int jId, int* count);

    [DllImport(Library, EntryPoint = "glfwGetJoystickButtons", CallingConvention = CallingConvention.Cdecl)]
    public static extern JoystickInputAction* GetJoystickButtons(int jId, int* count);

    [DllImport(Library, EntryPoint = "glfwGetJoystickHats", CallingConvention = CallingConvention.Cdecl)]
    public static extern JoystickHats* GetJoystickHats(int jId, int* count);

    [DllImport(Library, EntryPoint = "glfwGetJoystickName", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetJoystickName(int jId);

    [DllImport(Library, EntryPoint = "glfwGetJoystickGUID", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetJoystickGuid(int jId);

    [DllImport(Library, EntryPoint = "glfwSetJoystickUserPointer", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetJoystickUserPointer(int jId, void* ptr);

    [DllImport(Library, EntryPoint = "glfwGetJoystickUserPointer", CallingConvention = CallingConvention.Cdecl)]
    public static extern void* GetJoystickUserPointer(int jId);

    [DllImport(Library, EntryPoint = "glfwJoystickIsGamepad", CallingConvention = CallingConvention.Cdecl)]
    public static extern int JoystickIsGamepad(int jId);

    [DllImport(Library, EntryPoint = "glfwUpdateGamepadMappings", CallingConvention = CallingConvention.Cdecl)]
    public static extern int UpdateGamepadMappings(byte* newMapping);

    [DllImport(Library, EntryPoint = "glfwGetGamepadName", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetGamepadName(int jId);

    [DllImport(Library, EntryPoint = "glfwGetGamepadState", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetGamepadState(int jId, GamepadState* state);

    [DllImport(Library, EntryPoint = "glfwGetTime", CallingConvention = CallingConvention.Cdecl)]
    public static extern double GetTime();

    [DllImport(Library, EntryPoint = "glfwSetTime", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetTime(double time);

    [DllImport(Library, EntryPoint = "glfwGetTimerValue", CallingConvention = CallingConvention.Cdecl)]
    public static extern long GetTimerValue();

    [DllImport(Library, EntryPoint = "glfwGetTimerFrequency", CallingConvention = CallingConvention.Cdecl)]
    public static extern long GetTimerFrequency();

    [DllImport(Library, EntryPoint = "glfwGetCurrentContext", CallingConvention = CallingConvention.Cdecl)]
    public static extern Window* GetCurrentContext();

    [DllImport(Library, EntryPoint = "glfwSwapBuffers", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SwapBuffers(Window* window);

    [DllImport(Library, EntryPoint = "glfwExtensionSupported", CallingConvention = CallingConvention.Cdecl)]
    public static extern int ExtensionSupported(byte* extensionName);

    [DllImport(Library, EntryPoint = "glfwGetProcAddress", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetProcAddress(byte* procName);

    [DllImport(Library, EntryPoint = "glfwGetProcAddress", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetProcAddress(string procName);

    [DllImport(Library, EntryPoint = "glfwCreateWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern Window* CreateWindow(int width, int height, byte* title, Monitor* monitor, Window* share);

    [DllImport(Library, EntryPoint = "glfwGetPrimaryMonitor", CallingConvention = CallingConvention.Cdecl)]
    public static extern Monitor* GetPrimaryMonitor();

    [DllImport(Library, EntryPoint = "glfwDestroyWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern void DestroyWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwFocusWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern void FocusWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetFramebufferSize", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetFramebufferSize(Window* window, int* width, int* height);

    [DllImport(Library, EntryPoint = "glfwGetInputMode", CallingConvention = CallingConvention.Cdecl)]
    public static extern CursorModeValue GetInputMode(Window* window, CursorStateAttribute mode);

    [DllImport(Library, EntryPoint = "glfwGetInputMode", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetInputMode(Window* window, StickyAttributes mode);

    [DllImport(Library, EntryPoint = "glfwGetInputMode", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetInputMode(Window* window, LockKeyModAttribute mode);

    [DllImport(Library, EntryPoint = "glfwGetInputMode", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetInputMode(Window* window, RawMouseMotionAttribute mode);

    [DllImport(Library, EntryPoint = "glfwRestoreWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern void RestoreWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetVideoMode", CallingConvention = CallingConvention.Cdecl)]
    public static extern VideoMode* GetVideoMode(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwGetWindowAttrib", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetWindowAttrib(Window* window, WindowAttributeGetBool attribute);

    [DllImport(Library, EntryPoint = "glfwGetWindowAttrib", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetWindowAttrib(Window* window, WindowAttributeGetInt attribute);

    [DllImport(Library, EntryPoint = "glfwGetWindowAttrib", CallingConvention = CallingConvention.Cdecl)]
    public static extern ClientApi GetWindowAttrib(Window* window, WindowAttributeGetClientApi attribute);

    [DllImport(Library, EntryPoint = "glfwGetWindowAttrib", CallingConvention = CallingConvention.Cdecl)]
    public static extern ContextApi GetWindowAttrib(Window* window, WindowAttributeGetContextApi attribute);

    [DllImport(Library, EntryPoint = "glfwGetWindowAttrib", CallingConvention = CallingConvention.Cdecl)]
    public static extern OpenGlProfile GetWindowAttrib(Window* window, WindowAttributeGetOpenGlProfile attribute);

    [DllImport(Library, EntryPoint = "glfwGetWindowAttrib", CallingConvention = CallingConvention.Cdecl)]
    public static extern ReleaseBehavior GetWindowAttrib(Window* window, WindowAttributeGetReleaseBehavior attribute);

    [DllImport(Library, EntryPoint = "glfwGetWindowAttrib", CallingConvention = CallingConvention.Cdecl)]
    public static extern Robustness GetWindowAttrib(Window* window, WindowAttributeGetRobustness attribute);

    [DllImport(Library, EntryPoint = "glfwGetWindowSize", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetWindowSize(Window* window, int* width, int* height);

    [DllImport(Library, EntryPoint = "glfwGetWindowPos", CallingConvention = CallingConvention.Cdecl)]
    public static extern void GetWindowPos(Window* window, int* x, int* y);

    [DllImport(Library, EntryPoint = "glfwGetWindowMonitor", CallingConvention = CallingConvention.Cdecl)]
    public static extern Monitor* GetWindowMonitor(Window* window);

    [DllImport(Library, EntryPoint = "glfwHideWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern void HideWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwIconifyWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern void IconifyWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwMakeContextCurrent", CallingConvention = CallingConvention.Cdecl)]
    public static extern void MakeContextCurrent(Window* window);

    [DllImport(Library, EntryPoint = "glfwMaximizeWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern void MaximizeWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwPollEvents", CallingConvention = CallingConvention.Cdecl)]
    public static extern void PollEvents();

    [DllImport(Library, EntryPoint = "glfwPostEmptyEvent", CallingConvention = CallingConvention.Cdecl)]
    public static extern void PostEmptyEvent();

    [DllImport(Library, EntryPoint = "glfwWindowHint", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WindowHint(WindowHintInt hint, int value);

    [DllImport(Library, EntryPoint = "glfwWindowHint", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WindowHint(WindowHintBool hint, int value);

    [DllImport(Library, EntryPoint = "glfwWindowHint", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WindowHint(WindowHintClientApi hint, ClientApi value);

    [DllImport(Library, EntryPoint = "glfwWindowHint", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WindowHint(WindowHintReleaseBehavior hint, ReleaseBehavior value);

    [DllImport(Library, EntryPoint = "glfwWindowHint", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WindowHint(WindowHintContextApi hint, ContextApi value);

    [DllImport(Library, EntryPoint = "glfwWindowHint", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WindowHint(WindowHintRobustness hint, Robustness value);

    [DllImport(Library, EntryPoint = "glfwWindowHint", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WindowHint(WindowHintOpenGlProfile hint, OpenGlProfile value);

    [DllImport(Library, EntryPoint = "glfwWindowShouldClose", CallingConvention = CallingConvention.Cdecl)]
    public static extern int WindowShouldClose(Window* window);

    [DllImport(Library, EntryPoint = "glfwSetWindowUserPointer", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowUserPointer(Window* window, void* pointer);

    [DllImport(Library, EntryPoint = "glfwGetWindowUserPointer", CallingConvention = CallingConvention.Cdecl)]
    public static extern void* GetWindowUserPointer(Window* window);

    [DllImport(Library, EntryPoint = "glfwSetCharCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetCharCallback(Window* window, CharCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetCharModsCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetCharModsCallback(Window* window, CharModsCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetCursorEnterCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetCursorEnterCallback(Window* window, CursorEnterCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetCursorPosCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetCursorPosCallback(Window* window, CursorPosCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetDropCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetDropCallback(Window* window, DropCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetErrorCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetErrorCallback(ErrorCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetInputMode", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetInputMode(Window* window, CursorStateAttribute mode, CursorModeValue value);

    [DllImport(Library, EntryPoint = "glfwSetInputMode", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetInputMode(Window* window, StickyAttributes mode, int value);

    [DllImport(Library, EntryPoint = "glfwSetInputMode", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetInputMode(Window* window, LockKeyModAttribute mode, int value);

    [DllImport(Library, EntryPoint = "glfwSetInputMode", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetInputMode(Window* window, RawMouseMotionAttribute mode, int value);

    [DllImport(Library, EntryPoint = "glfwSetJoystickCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetJoystickCallback(JoystickCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetKeyCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetKeyCallback(Window* window, KeyCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetScrollCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetScrollCallback(Window* window, ScrollCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetMonitorCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetMonitorCallback(MonitorCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetMouseButtonCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetMouseButtonCallback(Window* window, MouseButtonCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetWindowCloseCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetWindowCloseCallback(Window* window, WindowCloseCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetWindowFocusCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetWindowFocusCallback(Window* window, WindowFocusCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetWindowIcon", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowIcon(Window* window, int count, Image* images);

    [DllImport(Library, EntryPoint = "glfwSetWindowIconifyCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetWindowIconifyCallback(Window* window, WindowIconifyCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetWindowMaximizeCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetWindowMaximizeCallback(Window* window, WindowMaximizeCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetFramebufferSizeCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetFramebufferSizeCallback(Window* window, FramebufferSizeCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetWindowContentScaleCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetWindowContentScaleCallback(Window* window, WindowContentScaleCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetWindowTitle", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowTitle(Window* window, byte* title);

    [DllImport(Library, EntryPoint = "glfwShowWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern void ShowWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwSetWindowSize", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowSize(Window* window, int width, int height);

    [DllImport(Library, EntryPoint = "glfwSetWindowSizeCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetWindowSizeCallback(Window* window, WindowSizeCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetWindowShouldClose", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowShouldClose(Window* window, int value);

    [DllImport(Library, EntryPoint = "glfwSetWindowMonitor", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowMonitor(Window* window, Monitor* monitor, int x, int y, int width, int height,
        int refreshRate);

    [DllImport(Library, EntryPoint = "glfwSetWindowPos", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetWindowPos(Window* window, int x, int y);

    [DllImport(Library, EntryPoint = "glfwSetWindowPosCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetWindowPosCallback(Window* window, WindowPosCallback callback);

    [DllImport(Library, EntryPoint = "glfwSetWindowRefreshCallback", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr SetWindowRefreshCallback(Window* window, WindowRefreshCallback callback);

    [DllImport(Library, EntryPoint = "glfwSwapInterval", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SwapInterval(int interval);

    [DllImport(Library, EntryPoint = "glfwWaitEvents", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WaitEvents();

    [DllImport(Library, EntryPoint = "glfwWaitEventsTimeout", CallingConvention = CallingConvention.Cdecl)]
    public static extern void WaitEventsTimeout(double timeout);

    [DllImport(Library, EntryPoint = "glfwGetClipboardString", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetClipboardString(Window* window);

    [DllImport(Library, EntryPoint = "glfwSetClipboardString", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetClipboardString(Window* window, byte* data);

    [DllImport(Library, EntryPoint = "glfwVulkanSupported", CallingConvention = CallingConvention.Cdecl)]
    public static extern int VulkanSupported();

    [DllImport(Library, EntryPoint = "glfwGetRequiredInstanceExtensions", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte** GetRequiredInstanceExtensions(uint* count);

    [DllImport(Library, EntryPoint = "glfwGetInstanceProcAddress", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetInstanceProcAddress(VkHandle instance, byte* procName);

    [DllImport(Library, EntryPoint = "glfwGetPhysicalDevicePresentationSupport",
        CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetPhysicalDevicePresentationSupport(VkHandle instance, VkHandle device, int queueFamily);

    [DllImport(Library, EntryPoint = "glfwCreateWindowSurface", CallingConvention = CallingConvention.Cdecl)]
    public static extern int CreateWindowSurface(VkHandle instance, Window* window, void* allocator,
        out VkHandle surface);

    [DllImport(Library, EntryPoint = "glfwGetWin32Adapter", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetWin32Adapter(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwGetWin32Monitor", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetWin32Monitor(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwGetWin32Window", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetWin32Window(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetWGLContext", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetWglContext(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetCocoaMonitor", CallingConvention = CallingConvention.Cdecl)]
    public static extern uint GetCocoaMonitor(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwGetCocoaWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetCocoaWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetNSGLContext", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetNsGlContext(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetX11Display", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetX11Display();

    [DllImport(Library, EntryPoint = "glfwGetX11Adapter", CallingConvention = CallingConvention.Cdecl)]
    public static extern UIntPtr GetX11Adapter(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwGetX11Monitor", CallingConvention = CallingConvention.Cdecl)]
    public static extern UIntPtr GetX11Monitor(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwGetX11Window", CallingConvention = CallingConvention.Cdecl)]
    public static extern UIntPtr GetX11Window(Window* window);

    [DllImport(Library, EntryPoint = "glfwSetX11SelectionString", CallingConvention = CallingConvention.Cdecl)]
    public static extern void SetX11SelectionString(byte* @string);

    [DllImport(Library, EntryPoint = "glfwGetX11SelectionString", CallingConvention = CallingConvention.Cdecl)]
    public static extern byte* GetX11SelectionString();

    [DllImport(Library, EntryPoint = "glfwGetGLXContext", CallingConvention = CallingConvention.Cdecl)]
    public static extern uint GetGlXContext(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetGLXWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern uint GetGlXWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetWaylandDisplay", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetWaylandDisplay();

    [DllImport(Library, EntryPoint = "glfwGetWaylandMonitor", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetWaylandMonitor(Monitor* monitor);

    [DllImport(Library, EntryPoint = "glfwGetWaylandWindow", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetWaylandWindow(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetEGLDisplay", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetEGLDisplay();

    [DllImport(Library, EntryPoint = "glfwGetEGLContext", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetEglContext(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetEGLSurface", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetEglSurface(Window* window);

    [DllImport(Library, EntryPoint = "glfwGetOSMesaColorBuffer", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetOSMesaColorBuffer(Window* window, int* width, int* height, int* format,
        void** buffer);

    [DllImport(Library, EntryPoint = "glfwGetOSMesaDepthBuffer", CallingConvention = CallingConvention.Cdecl)]
    public static extern int GetOSMesaDepthBuffer(Window* window, int* width, int* height, int* bytesPerValue,
        void** buffer);

    [DllImport(Library, EntryPoint = "glfwGetOSMesaContext", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr GetOSMesaContext(Window* window);
}